﻿<%@ WebHandler Language="C#" Class="ZSDeviceMonitorHandler" %>

using System;
using System.Web;
using System.Web.SessionState;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Collections;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using BusinessRule.Business;
using BusinessRule.IBusiness;
using BusinessRule.BusinessFactory;
using Newtonsoft.Json;
using DatabaseAccess.DBUtility;
using BusinessRule.DTO;

public class ZSDeviceMonitorHandler : IHttpHandler, IRequiresSessionState {
    
     public void ProcessRequest(HttpContext context)
    {
        try
        {
            var action = context.Request["action"].ToString();
            switch (action)
            {
                case "GetTop100SQL":
                    GetTop100SQL(context);
                    break;
                case "getTop100SlowSQL":
                    GetTop100SlowSQL(context);
                    break;
                case "GetTableAccessFullSQL":
                    GetTableAccessFullSQL(context);
                    break;
                case "GetTableUseSQL":
                    GetTableUseSQL(context);
                    break;
                case "GetTableSpaceSQL":
                    GetTableSpaceSQL(context);
                    break;
                case "GetWebServerData":
                    GetWebServerData(context);
                    break;
                case "getSyncServiceInfo":
                    getSyncServiceInfo(context);
                    break;
                case "saveSyncServiceInfo":
                    saveSyncServiceInfo(context);
                    break;
                case "deleteSyncServiceInfo":
                    deleteSyncServiceInfo(context);
                    break; 
                case"openStopServiceInfo":
                    openStopServiceInfo(context);
                    break;  
                case"buildSyncServiceInfo":
                    buildSyncServiceInfo(context);
                    break;
                default:
                    break;
            }
        }
        catch (Exception ex)
        {
            var result = new uMESProcessResult();
            result.Result = false;
            result.Message = ex.Message;
            context.Response.ContentType = "text/html";
            context.Response.Write(JsonConvert.SerializeObject(result));
        }
    }
    public bool IsReusable {
        get {
            return false;
        }
    }


    private void GetTop100SQL(HttpContext context) 
    {
        var sql = @"SELECT * FROM (SELECT S.SQL_TEXT,S.EXECUTIONS,U.USERNAME,
               RANK() OVER(ORDER BY EXECUTIONS DESC) EXEC_RANK
          FROM V$SQL S
          LEFT JOIN ALL_USERS U ON U.USER_ID = S.PARSING_USER_ID) T WHERE EXEC_RANK <= 100";
        var result = new uMESProcessResult();
        result.DBTable = DatabaseHelper.Query_ReturnDatTable(sql);
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    private void GetTop100SlowSQL(HttpContext context) 
    {
        var sql = @"SELECT *
            FROM (SELECT SA.SQL_TEXT,
               SA.SQL_FULLTEXT,
               SA.EXECUTIONS ,
               ROUND(SA.ELAPSED_TIME / 1000000, 2) TOTALTIME,
               ROUND(SA.ELAPSED_TIME / 1000000 / SA.EXECUTIONS, 2) AVGTIME,
               SA.COMMAND_TYPE,
               U.USERNAME,
               SA.HASH_VALUE
          FROM V$SQLAREA SA
          LEFT JOIN ALL_USERS U
            ON SA.PARSING_USER_ID = U.USER_ID
         WHERE SA.EXECUTIONS > 0 AND SQL_TEXT LIKE 'SELECT%' AND U.USERNAME='IN1'
         ORDER BY (SA.ELAPSED_TIME / SA.EXECUTIONS) DESC)
        WHERE ROWNUM <= 100";
        var result = new uMESProcessResult();
        result.DBTable = DatabaseHelper.Query_ReturnDatTable(sql);
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    private void GetTableAccessFullSQL(HttpContext context)
    {
        var sql = @"SELECT v.OBJECT_NAME,v.CPU_COST,v.IO_COST,v.TEMP_SPACE,v.OTHER_XML,s.SQL_TEXT
          from v$sql_plan v
          LEFT JOIN v$sqlarea s ON s.SQL_ID=v.SQL_ID AND s.HASH_VALUE=v.HASH_VALUE AND s.PLAN_HASH_VALUE=v.PLAN_HASH_VALUE
         where v.operation = 'TABLE ACCESS'
           and v.OPTIONS = 'FULL'
           and v.OBJECT_OWNER='IN1' AND v.OBJECT_NAME<>'SCHEDULEDBUSINESSRULE'";
        var result = new uMESProcessResult();
        result.DBTable = DatabaseHelper.Query_ReturnDatTable(sql);
        context.Response.Write(JsonConvert.SerializeObject(result));
    }
    
    private void GetTableUseSQL(HttpContext context)
    {
        var sql = @"SELECT tbs,sum(totalM) totalM,sum(usedM) usedM,sum(remainedM) remainedM, ROUND(sum(usedM)/sum(totalM)*100,4) usedMB, ROUND(sum(remainedM)/sum(totalM)*100,4) remainedMB  
	FROM(  SELECT b.file_id ID,b.tablespace_name tbs,b.file_name name,b.bytes/1024/1024 totalM,(b.bytes-sum(nvl(a.bytes,0)))/1024/1024 usedM,sum(nvl(a.bytes,0)/1024/1024) remainedM,  
		sum(nvl(a.bytes,0)/(b.bytes)*100),(100 - (sum(nvl(a.bytes,0))/(b.bytes)*100))  
		FROM dba_free_space a,dba_data_files b  
		WHERE a.file_id = b.file_id  GROUP BY b.tablespace_name,b.file_name,b.file_id,b.bytes  ORDER BY b.tablespace_name  
	)  GROUP BY tbs ";
        var result = new uMESProcessResult();
        result.DBTable = DatabaseHelper.Query_ReturnDatTable(sql);
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    private void GetTableSpaceSQL(HttpContext context) 
    {
        var sql = @"select FILE_NAME,TABLESPACE_NAME,ROUND(b.bytes/1024/1024,4) totalM,ROUND(b.USER_BYTES/1024/1024,4) USER_BYTES from dba_data_files b where 1=1";
        if(!string.IsNullOrWhiteSpace(context.Request["tabname"].ToString())){
            sql += " AND b.tablespace_name='" + context.Request["tabname"].ToString() + "'";
        }
        sql += " order by TABLESPACE_NAME,FILE_NAME";
        var result = new uMESProcessResult();
        result.DBTable = DatabaseHelper.Query_ReturnDatTable(sql);
        context.Response.Write(JsonConvert.SerializeObject(result));
    }

    private void GetWebServerData(HttpContext context) 
    {
        //核心数
        int cpuNum = Environment.ProcessorCount;
        string computerName = Environment.MachineName;
        string appRAM = ((double)Process.GetCurrentProcess().WorkingSet64 / 1048576).ToString("N2") + " MB";
        var programStartTime = Process.GetCurrentProcess().StartTime;
        string programRunTime = ShellHelper.FormatTime(long.Parse((DateTime.Now - programStartTime).TotalMilliseconds.ToString().Split('.')[0]));
        var data = new
        {
            cpu = GetComputerInfo(),
            disk = GetDiskInfos(),
            sys = new { cpuNum, computerName },
        };
        var result = new uMESProcessResult();
        result.ReturnData = data;
        context.Response.Write(JsonConvert.SerializeObject(result));
    }
    /// <summary>
    /// 内存使用情况
    /// </summary>
    /// <returns></returns>
    public static MemoryMetrics GetComputerInfo()
    {
        try
        {
            MemoryMetrics memoryMetrics = GetWindowsMetrics();

            memoryMetrics.FreeRam = Math.Round(memoryMetrics.Free / 1024, 2) + "GB";
            memoryMetrics.UsedRam = Math.Round(memoryMetrics.Used / 1024, 2) + "GB";
            memoryMetrics.TotalRAM = Math.Round(memoryMetrics.Total / 1024, 2) + "GB";
            memoryMetrics.RAMRate = Math.Ceiling(100 * memoryMetrics.Used / memoryMetrics.Total).ToString();//+ "%";
            memoryMetrics.CPURate = Math.Ceiling(double.Parse(GetCPURate())).ToString(); //+ "%";
            return memoryMetrics;
        }
        catch (Exception ex)
        {
            Console.WriteLine("获取内存使用出错，msg=" + ex.Message + "," + ex.StackTrace);
        }
        return new MemoryMetrics();
    }

    /// <summary>
    /// windows系统获取内存信息
    /// </summary>
    /// <returns></returns>
    public static MemoryMetrics GetWindowsMetrics()
    {
        string output = ShellHelper.Cmd("wmic", "OS get FreePhysicalMemory,TotalVisibleMemorySize /Value");
        var metrics = new MemoryMetrics();
        var lines = output.Trim().Split('\n', (char)StringSplitOptions.RemoveEmptyEntries);

        if (lines.Length <= 0) return metrics;

        var freeMemoryParts = lines[0].Split('=', (char)StringSplitOptions.RemoveEmptyEntries);
        var totalMemoryParts = lines[1].Split('=', (char)StringSplitOptions.RemoveEmptyEntries);

        metrics.Total = Math.Round(double.Parse(totalMemoryParts[1]) / 1024, 0);
        metrics.Free = Math.Round(double.Parse(freeMemoryParts[1]) / 1024, 0);//m
        metrics.Used = metrics.Total - metrics.Free;

        return metrics;
    }
    
    /// <summary>
    /// 获取内存大小
    /// </summary>
    /// <returns></returns>
    public static List<DiskInfo> GetDiskInfos()
        {
            List<DiskInfo> diskInfos = new List<DiskInfo>();

            var driv =System.IO.DriveInfo.GetDrives();
            foreach (var item in driv)
            {
                try
                {
                    var obj = new DiskInfo()
                    {
                        DiskName = item.Name,
                        TypeName = item.DriveType.ToString(),
                        TotalSize = item.TotalSize / 1024 / 1024 / 1024,
                        AvailableFreeSpace = item.AvailableFreeSpace / 1024 / 1024 / 1024,
                    };
                    obj.Used = obj.TotalSize - obj.AvailableFreeSpace;
                    obj.AvailablePercent = decimal.Ceiling(obj.Used / (decimal)obj.TotalSize * 100);
                    diskInfos.Add(obj);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("获取磁盘信息出错了" + ex.Message);
                    continue;
                }
            }
            return diskInfos;
        }
  public static string GetCPURate()
        {
            string cpuRate;
            string output = ShellHelper.Cmd("wmic", "cpu get LoadPercentage"); Console.WriteLine(output);
            cpuRate = output.Replace("LoadPercentage", string.Empty).Trim().Replace("\r\n", "@");
            string[] str = cpuRate.Split('@');
            if (str.Length == 2) {
                cpuRate = str[0].Trim();//(float.Parse(str[0].Trim()) / double.Parse(str[1].Trim())).ToString();
            }
            return cpuRate;
        }

  private void getSyncServiceInfo(HttpContext context)
  {
      string servicename = context.Request["servicename"].ToString();
      string pageSize = context.Request["pageSize"].ToString();
      string pageNumber = context.Request["pageNumber"].ToString();
      string selectSQL = @"SELECT s.*,null servicestatus FROM sync_ServiceInfo s where 1=1 ";
      if (!string.IsNullOrWhiteSpace(servicename))
      {
          selectSQL += " and servicename like '%" + servicename + "%'";
      }
      //selectSQL += " and serviceIP='" +context.Request.ServerVariables.Get("Local_Addr").ToString() + "'";
      selectSQL += "order by createtime ";
      var paraPage = new uMESPagingDataDTO();
      paraPage.CurrentPageIndex = Convert.ToInt32(pageNumber);
      paraPage.PageSize = Convert.ToInt32(pageSize);
      paraPage.strSQL = selectSQL;
      uMESProcessResult result = DatabaseHelper.RunProcedureForPage(paraPage);
      foreach(DataRow row in result.DBTable.Rows){
          row["servicestatus"] = ServicesExists(row["servicename"].ToString(),"1");
      }
      context.Response.Write(JsonConvert.SerializeObject(result));
  }

  private void saveSyncServiceInfo(HttpContext context)
  {
      DataTable data = JsonConvert.DeserializeObject<DataTable>(context.Request["data"].ToString());
      var insertSQL = @"insert into sync_ServiceInfo (ID,servicename,serviceProjectpath,serviceDesc,serviceIP,createtime)values('{0}','{1}','{2}','{3}','{4}',sysdate)";
      var arrList = new ArrayList();
      var existMSG = string.Empty;
      foreach (DataRow row in data.Rows)
      {
          if (string.IsNullOrWhiteSpace(row["ID"].ToString()))
          {
              arrList.Add(string.Format(insertSQL, Guid.NewGuid(), row["servicename"], row["serviceProjectpath"], row["serviceDesc"], row["serviceIP"]));

          }
          else
          {
              arrList.Add(string.Format("update sync_ServiceInfo set servicename='{0}',serviceProjectpath='{1}',serviceDesc='{2}',serviceIP='{3}',lastchangetime=sysdate where ID='{4}'", row["servicename"], row["serviceProjectpath"], row["serviceDesc"], row["serviceIP"], row["id"]));
          }
      }
      uMESProcessResult result = new uMESProcessResult();
      if (arrList.Count > 0)
      {
          result.Result = DatabaseHelper.ExecuteSqlListTran(arrList);
      }
      result.Message = result.Result ? "保存成功" : "保存失败";
      context.Response.Write(JsonConvert.SerializeObject(result));
  }

  private void deleteSyncServiceInfo(HttpContext context)
  {
      DataTable data = JsonConvert.DeserializeObject<DataTable>(context.Request["data"].ToString());
      var arrList = new ArrayList();
      foreach (DataRow row in data.Rows)
      {
          arrList.Add(string.Format("delete from sync_ServiceInfo  where ID='{0}'", row["ID"]));
      }
      uMESProcessResult result = new uMESProcessResult();
      if (arrList.Count > 0)
      {
          result.Result = DatabaseHelper.ExecuteSqlListTran(arrList);
      }
      result.Message = result.Result ? "删除成功" : "删除失败";
      context.Response.Write(JsonConvert.SerializeObject(result));
  }

  private void openStopServiceInfo(HttpContext context) 
  {
      var  para = JsonConvert.DeserializeObject<Dictionary<string,string>>(context.Request["data"].ToString());
      uMESProcessResult result = new uMESProcessResult();
      //string output = ShellHelper.Cmd(@"C:\Windows\System32\cmd.exe", " Net Start " + para["SERVICENAME"]);
      result.Result = para["SERVICESTATUS"].Equals("True") ? ServiceStop(para["SERVICENAME"]) : ServiceStar(para["SERVICENAME"]);
      result.Message = (para["SERVICESTATUS"].Equals("True") ? "停止服务" : "启动服务") + (result.Result ? "成功" : "失败");
     context.Response.Write(JsonConvert.SerializeObject(result));
  }  
    
    /// <summary>
    /// 服务重新生成
    /// </summary>
    /// <param name="context"></param>
  private void buildSyncServiceInfo(HttpContext context)
  {
      string ServicePath = context.Request["servicePath"].ToString();
      uMESProcessResult result = new uMESProcessResult();
      if (System.IO.File.Exists(ServicePath))
      {
          string output = ShellHelper.Cmd("C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MsBuild.exe", ServicePath + " -p:Configuration=DEBUG");
          result.Result = output.Contains("已成功生成");
          result.Message = result.Result ? "生成成功" : "生成失败";
      }
      else {
          result.Message = "服务项目不存在";
      }
      context.Response.Write(JsonConvert.SerializeObject(result));
  }

  //监测服务是否启动
  private bool ServicesExists(string serviceName,string type)
  {
      bool isbn = false;
      //获取所有服务
      System.ServiceProcess.ServiceController[] services = System.ServiceProcess.ServiceController.GetServices();
      try
      {
          foreach (System.ServiceProcess.ServiceController service in services)
          {
              if (service.ServiceName.ToUpper() == serviceName.ToUpper())
              {
                  var sc = new System.ServiceProcess.ServiceController(serviceName.ToUpper());
                  if (!string.IsNullOrWhiteSpace(type)) { isbn = sc.Status.ToString().Equals("Running"); } else { isbn = true; }
                  break;
              }
          }
          return isbn;
      }
      catch (Exception ex)
      {
          return false;
      }
  }

  //启动服务
  private bool ServiceStar(string serviceName)
  {
      bool isbn = false;
      try
      {
          if (ServicesExists(serviceName,null))
          {
              System.ServiceProcess.ServiceController star_service = new System.ServiceProcess.ServiceController(serviceName);
              if (star_service.Status != System.ServiceProcess.ServiceControllerStatus.Running &&
              star_service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
              {
                  star_service.Start();
                  star_service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
                  star_service.Close();
                  for (int i = 0; i < 60; i++)
                  {
                      star_service.Refresh();
                      System.Threading.Thread.Sleep(1000);
                      if (star_service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                      {
                          isbn = true;
                          break;
                      }
                      if (i == 59)
                      {
                          isbn = false;
                      }
                  }
              }
          }
      }
      catch (Exception ex)
      {
          return false;
      }
      return isbn;
  }

  //停止服务
  private bool ServiceStop(string serviceName)
  {
      bool isbn = false;

      try
      {
          if (ServicesExists(serviceName,null))
          {
              System.ServiceProcess.ServiceController star_service = new System.ServiceProcess.ServiceController(serviceName);
              if (star_service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
              {
                  star_service.Stop();
                  star_service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
                  star_service.Close();
                  for (int i = 0; i < 60; i++)
                  {
                      star_service.Refresh();
                      System.Threading.Thread.Sleep(1000);
                      if (star_service.Status == System.ServiceProcess.ServiceControllerStatus.Stopped)
                      {
                          isbn = true;
                          break;
                      }
                      if (i == 59)
                      {
                          isbn = false;
                      }
                  }
              }
          }
      }
      catch (Exception ex)
      {
          return false;
      }
      return isbn;
  }    
    
    
      
   public class ShellHelper
   {
      /// <summary>
      /// windows系统命令
      /// </summary>
      /// <param name="fileName"></param>
      /// <param name="args"></param>
      /// <returns></returns>
      public static string Cmd(string fileName, string args)
      {
          string output = string.Empty;

          var info = new ProcessStartInfo();
          info.FileName = fileName;
          info.Arguments = args;
          info.RedirectStandardOutput = true;
          info.UseShellExecute = false;
          info.RedirectStandardInput = true;

          using (var process = Process.Start(info))
          {
              output = process.StandardOutput.ReadToEnd();
          }
          return output;
      }
      public static string FormatTime(long ms)
      {
          int ss = 1000;
          int mi = ss * 60;
          int hh = mi * 60;
          int dd = hh * 24;

          long day = ms / dd;
          long hour = (ms - day * dd) / hh;
          long minute = (ms - day * dd - hour * hh) / mi;
          long second = (ms - day * dd - hour * hh - minute * mi) / ss;
          long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;

          string sDay = day < 10 ? "0" + day : "" + day; //天
          string sHour = hour < 10 ? "0" + hour : "" + hour;//小时
          string sMinute = minute < 10 ? "0" + minute : "" + minute;//分钟
          string sSecond = second < 10 ? "0" + second : "" + second;//秒
          string sMilliSecond = milliSecond < 10 ? "0" + milliSecond : "" + milliSecond;//毫秒
          sMilliSecond = milliSecond < 100 ? "0" + sMilliSecond : "" + sMilliSecond;

          return string.Format("{0} 天 {1} 小时 {2} 分 {3} 秒", sDay, sHour, sMinute, sSecond);
      }
    }
    
    public class DiskInfo
    {
        /// <summary>
        /// 磁盘名
        /// </summary>
        public string DiskName { get; set; }
        public string TypeName { get; set; }
        public long TotalFree { get; set; }
        public long TotalSize { get; set; }
        /// <summary>
        /// 已使用
        /// </summary>
        public long Used { get; set; }
        /// <summary>
        /// 可使用
        /// </summary>
        public long AvailableFreeSpace { get; set; }
        public decimal AvailablePercent { get; set; }
    }

    /// <summary>
    /// 内存信息
    /// </summary>
    public class MemoryMetrics
    {
        [JsonIgnore]
        public double Total { get; set; }
        [JsonIgnore]
        public double Used { get; set; }
        [JsonIgnore]
        public double Free { get; set; }

        public string UsedRam { get; set; }
        /// <summary>
        /// CPU使用率%
        /// </summary>
        public string CPURate { get; set; }
        /// <summary>
        /// 总内存 GB
        /// </summary>
        public string TotalRAM { get; set; }
        /// <summary>
        /// 内存使用率 %
        /// </summary>
        public string RAMRate { get; set; }
        /// <summary>
        /// 空闲内存
        /// </summary>
        public string FreeRam { get; set; }
    }

}